package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.constant.GlobalConstant;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.threadLocal.AppThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Autowired
    RestHighLevelClient client;
    @Autowired
    ApUserSearchService apUserSearchService;
    @Override
    public ResponseResult search(UserSearchDto dto) throws IOException {
        if(dto==null||StringUtils.isBlank(dto.getSearchWords()))
        {
            throw new CustomException(AppHttpCodeEnum.PARAMS_NOT_NULL);
        }
        if (dto.getPageSize()==null||dto.getMinBehotTime()==null||dto.getPageSize()<=0)
        {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.setPageSize(Math.min(dto.getPageSize(),GlobalConstant.MAX_PAGE_SIZE));
        //TODO 异步调用保存搜索记录
        apUserSearchService.insert(dto.getSearchWords(),AppThreadLocalUtil.getUserId());
        SearchRequest searchRequest=new SearchRequest(GlobalConstant.APP_INFO_ARTICLE_TAG);

        searchRequest.source().query(
                QueryBuilders.boolQuery()
                    .must(QueryBuilders.queryStringQuery(dto.getSearchWords()).field(GlobalConstant.CONTENT_TAG).field(GlobalConstant.TITLE_TAG).defaultOperator(Operator.OR))
                    .filter(QueryBuilders.rangeQuery(GlobalConstant.PUBLISH_TIME_TAG).lt(dto.getMinBehotTime().getTime()))
        )
                .from(0).size(dto.getPageSize())
                .sort(GlobalConstant.PUBLISH_TIME_TAG,SortOrder.DESC)
                .highlighter(new HighlightBuilder()
                        .field(GlobalConstant.TITLE_TAG)
                        .preTags(GlobalConstant.HIGH_PRE_TAGS)
                        .postTags(GlobalConstant.HIGH_POST_TAGS)
                )
        ;

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        List<Map> result=responseParseMaps(response);
        return ResponseResult.okResult(result);
    }

    private List<Map> responseParseMaps(SearchResponse response) {
        List<Map> result=new ArrayList<>();
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            result.add(SearchHitParseMap(hit));
        }
        return result;
    }
    public Map<String, Object> SearchHitParseMap(SearchHit hit)
    {
        Map<String, Object> map = hit.getSourceAsMap();
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        if(highlightFields==null||highlightFields.isEmpty())
        {
            map.put(GlobalConstant.H_TITLE_TAG,map.get(GlobalConstant.TITLE_TAG));
            return map;
        }
//        Set<Map.Entry<String, HighlightField>> entries = highlightFields.entrySet();
//        for (Map.Entry<String, HighlightField> entry : entries) {
//            map.put(entry.getKey(),entry.getValue().getFragments()[0].toString());
//        }
        Text[] titles = highlightFields.get(GlobalConstant.TITLE_TAG).getFragments();
        String title = StringUtils.join(titles);
        map.put(GlobalConstant.H_TITLE_TAG,title);
        return map;
    }
}
